import go from "gojs";
import timer from "@/utils/setTime";
import { parseTime } from "@/utils/index";
import { getRealDataAnds } from "@/api/configuration";
var vm = null;
var GOJS = {};
GOJS.$GO = go.GraphObject.make;

function setVm(vue) {
    vm = vue;
}

/**
 * 定制节点/连线模板
 * @param obj
 * @param pa
 */
GOJS.template = function(obj, pa) {
    obj.nodeTemplateMap.add(
        "Comment", // 【自定义】 标签
        GOJS.$GO(
            go.Node,
            "Auto", {
                doubleClick: pa[0],
            },
            GOJS.nodeStyle(), {
                locationSpot: new go.Spot(0.5, 0.5),
                resizable: true,
            },
            GOJS.$GO(
                go.Shape,
                "Rectangle", {
                    fill: "#1E0EB3",
                    opacity: 1,
                    stroke: null,
                },
                new go.Binding("fill", "fill", function(num) {
                    return num;
                }),
                new go.Binding("opacity", "fill", function(fill) {
                    if (fill == 1) {
                        return 0;
                    }
                    return 1;
                })
            ),
            GOJS.$GO(
                go.TextBlock, {
                    margin: 5,
                    wrap: go.TextBlock.WrapFit,
                    textAlign: "center",
                    editable: false,
                    font: "bold 12pt Helvetica, Arial, sans-serif",
                    stroke: "#409EFF",
                },
                new go.Binding("stroke", "stroke", function(stroke) {
                    // 定义字体颜色
                    if (stroke != null && stroke != "" && stroke != undefined) {
                        return stroke;
                    }

                    return "#409EFF";
                }),
                new go.Binding("font", "fontSizeAndfontFamily", function(
                    fontSizeAndfontFamily
                ) {
                    if (fontSizeAndfontFamily) {
                        return fontSizeAndfontFamily;
                    } else {
                        return "bold 20pt 微软雅黑,宋体,Helvetica, Arial, sans-serif";
                    }
                }),
                new go.Binding("text", "name").makeTwoWay()
            ),
            new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(
                go.Size.stringify
            ), {
                toolTip: GOJS.$GO(
                    go.Adornment,
                    "Auto",
                    GOJS.$GO(go.Shape, {
                        fill: "lightyellow",
                    }),
                    GOJS.$GO(
                        go.TextBlock, {
                            margin: 10,
                        },
                        new go.Binding("text", "", function(d) {
                            return d.name;
                        })
                    )
                ),
            }
        )
    );
    obj.nodeTemplateMap.add(
        "datatitle", // 【数据标签】
        GOJS.$GO(
            go.Node,
            "Auto", {
                doubleClick: pa[0],
            },
            GOJS.nodeStyle(), {
                locationSpot: new go.Spot(0.5, 0.5),
                resizable: true,
            },
            GOJS.$GO(
                go.Shape,
                "Rectangle", {
                    fill: "#409EFF",
                    opacity: 0,
                    stroke: null,
                },
                new go.Binding("fill", "fill", function(num) {
                    if (num) {
                        return num;
                    } else {
                        return "#409EFF";
                    }
                }),
                new go.Binding("opacity", "fill", function(fill) {
                    if (fill == null) {
                        return 0;
                    }
                    if (fill == 1) {
                        return 0;
                    }
                    return 1;
                })
            ),
            GOJS.$GO(
                go.TextBlock, {
                    margin: 5,
                    maxSize: new go.Size(200, NaN),
                    wrap: go.TextBlock.WrapFit,
                    textAlign: "center",
                    editable: false,
                    font: "bold 12pt Helvetica, Arial, sans-serif",
                    // stroke: '#454545'
                    stroke: "#409EFF",
                },
                new go.Binding("stroke", "stroke", function(stroke) {
                    // 定义字体颜色，默认为黑色
                    if (stroke != null && stroke != "" && stroke != undefined) {
                        return stroke;
                    }
                    return "#409EFF";
                }),
                new go.Binding("font", "fontSizeAndfontFamily", function(
                    fontSizeAndfontFamily
                ) {
                    // 定义字体系列
                    return fontSizeAndfontFamily;
                }),
                new go.Binding("text", "", function(d) {
                    if (d.enums_value) {
                        return d.enums_value;
                    }
                    if (d.value !== null && d.value !== undefined) {
                        return d.value;
                    }
                    if (d.vname !== null && d.vname !== undefined) {
                        return d.vname;
                    }
                    if (d.nname !== null && d.nname !== undefined) {
                        return d.nname;
                    }
                    if (d.name !== null && d.name !== undefined) {
                        return d.name;
                    }
                }).makeTwoWay()
            ), {
                toolTip: GOJS.$GO(
                    go.Adornment,
                    "Auto",
                    GOJS.$GO(go.Shape, {
                        fill: "lightyellow",
                    }),
                    GOJS.$GO(
                        go.TextBlock, {
                            margin: 10,
                        },
                        new go.Binding("text", "", function(d) {
                            var name = d.nname || "数据标签";
                            if (d.vname !== null && d.vname !== undefined) {
                                name = d.vname;
                            }
                            if (
                                d.onLine == "在线" &&
                                d.warning != null &&
                                d.warning != undefined &&
                                d.warning == 0
                            ) {
                                return `名称:${name}\n\n 日期:${d.date} \n\n 报警状态:是 \n\n 在线状态:${d.onLine}`;
                            }
                            if (d.onLine) {
                                return `名称:${name}\n\n 日期:${d.date} \n\n 在线状态:${d.onLine}`;
                            }
                            if (d.date) {
                                return "名称:" + name + "\n\n" + "日期:" + d.date;
                            } else {
                                return "名称:" + name;
                            }
                        })
                    )
                ),
            }
        )
    );
    obj.nodeTemplateMap.add(
        "pic",
        GOJS.$GO(
            go.Node,
            "Auto", {
                doubleClick: pa[0],
            },
            GOJS.nodeStyle(), {
                locationSpot: new go.Spot(0.5, 0.5),
                locationObjectName: "PICVER",
                resizable: true,
                resizeObjectName: "PICVER",
            },
            GOJS.$GO(
                go.Picture, {
                    name: "PICVER",
                    imageStretch: go.GraphObject.Uniform,
                },
                new go.Binding("source", "", function(d) {
                    var yd = 0;
                    if (d.nid == 0) {
                        return "";
                    }
                    if (d.yd) {
                        yd = d.yd;
                    }

                    let path = require("@/assets/images/node_pic/" +
                        d.nid +
                        "-" +
                        yd +
                        ".png");
                    return path;
                }),
                new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(
                    go.Size.stringify
                )
            ),
            GOJS.$GO(
                go.TextBlock, {
                    margin: new go.Margin(3, 0, 0, 0),
                    editable: false,
                    isMultiline: false,
                },
                new go.Binding("text", "text")
            ),
            GOJS.makePort("C", go.Spot.Center, true, true), {
                toolTip: GOJS.$GO(
                    go.Adornment,
                    "Auto",
                    GOJS.$GO(go.Shape, {
                        fill: "lightyellow",
                    }),
                    GOJS.$GO(
                        go.TextBlock, {
                            margin: 10,
                        },
                        new go.Binding("text", "", function(d) {
                            if (d.name) {
                                return d.name;
                            }
                        })
                    )
                ),
            }
        )
    );

    obj.nodeTemplateMap.add(
        "nodeLink",
        GOJS.$GO(
            go.Node,
            "Spot",
            GOJS.nodeStyle(),
            new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
                go.Point.stringify
            ),
            GOJS.$GO(
                go.Panel,
                "Auto",
                GOJS.$GO(
                    go.Shape,
                    "Circle", {
                        minSize: new go.Size(30, 30),
                        fill: "yellow",
                        stroke: null,
                    },
                    new go.Binding("opacity")
                ),
                GOJS.$GO(
                    go.TextBlock,
                    "", {
                        textAlign: "right",
                        font: "bold 11pt Helvetica, Arial, sans-serif",
                    },
                    new go.Binding("text")
                )
            ),
            GOJS.makePort("C", go.Spot.Center, true, true), {
                toolTip: GOJS.$GO(
                    go.Adornment,
                    "Auto",
                    GOJS.$GO(go.Shape, {
                        fill: "lightyellow",
                    }),
                    GOJS.$GO(
                        go.TextBlock, {
                            margin: 10,
                        },
                        new go.Binding("text", "", function(d) {
                            return d.name;
                        })
                    )
                ),
            }
        )
    );
    obj.linkTemplate = GOJS.$GO(
        go.Link, {
            doubleClick: pa[0],
            toShortLength: -2,
            fromShortLength: -2,
            layerName: "Background",
            corner: 15,
            reshapable: true,
            resegmentable: true,
        }, {
            adjusting: go.Link.Stretch,
        }, // optional
        new go.Binding("points", "points").makeTwoWay(),
        GOJS.$GO(
            go.Shape, {
                isPanelMain: true,
                stroke: "#CCC",
                strokeWidth: 10,
            },
            new go.Binding("stroke", "", function(d) {
                if (d.stroke) {
                    return d.stroke;
                }
                return "#ccc";
            }),
            new go.Binding("strokeWidth", "strokeWidth", function(strokeWidth) {
                if (strokeWidth) {
                    return strokeWidth * 5;
                }
                return 10;
            })
        ),
        GOJS.$GO(
            go.Shape, {
                isPanelMain: true,
                stroke: "#409EFF",
                strokeWidth: 2,
                name: "PIPE",
                strokeDashArray: [20, 40],
            },
            new go.Binding("strokeWidth", "strokeWidth", function(strokeWidth) {
                if (strokeWidth) {
                    return strokeWidth;
                }
                return 2;
            })
        )
    );
};

/**
 * 节点基础样式
 * @returns {{locationSpot: (L.Center|*|Q.Center), mouseEnter: Function, mouseLeave: Function}[]}
 */
GOJS.nodeStyle = function() {
    return [
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(
            go.Point.stringify
        ),
        {
            locationSpot: go.Spot.Center,
            mouseEnter: function(e, obj) {
                GOJS.showPorts(obj.part, true);
            },
            mouseLeave: function(e, obj) {
                GOJS.showPorts(obj.part, false);
            },
        },
    ];
};

/**
 * 自定义连线
 * @param name 名称
 * @param spot 位置(上下左右中)
 * @param output 是否连出
 * @param input  是否连进
 * @returns {*}
 */
GOJS.makePort = function(name, spot, output, input) {
    return GOJS.$GO(go.Shape, "Circle", {
        fill: "transparent",
        stroke: null,
        desiredSize: new go.Size(8, 8),
        alignment: spot,
        alignmentFocus: spot,
        portId: name,
        fromSpot: spot,
        toSpot: spot,
        fromLinkable: output,
        toLinkable: input,
        cursor: "pointer",
    });
};

/**
 * 鼠标悬浮时显示可连线的点
 * @param node
 * @param show
 */
GOJS.showPorts = function(node, show) {
    var diagram = node.diagram;
    if (!diagram || diagram.isReadOnly || !diagram.allowLink) return;
    node.ports.each(function(port) {
        port.stroke = show ? "red" : null;
    });
};

/**
 *
 * @param {画布内容} side
 */
function GOJSInit() {
    GOJS.myDiagram = GOJS.$GO(go.Diagram, "myDiagramDiv", {
        initialContentAlignment: go.Spot.Center, // 整个拓扑图的位置
        "grid.gridCellSize": new go.Size(5, 5), // 最小偏移量
        "draggingTool.isGridSnapEnabled": true,
        "resizingTool.isGridSnapEnabled": true,
        "rotatingTool.snapAngleMultiple": 90,
        "grid.visible": vm.gridVisible,
        LinkDrawn: GOJS.showLinkLabel,
        LinkRelinked: GOJS.showLinkLabel,
        "rotatingTool.snapAngleEpsilon": 45,
        "undoManager.isEnabled": true,
        initialScale: 0.6, // 初始化显示比例
        allowDrop: true,
    });
    GOJS.template(GOJS.myDiagram, [GOJS.mClick]);
    GOJS.loopNode();
    GOJS.loopLink(); // 动态特效开始执行
    GOJS.isReadOnly(true); // 默认只读
}

/**
 * 加载图形数据
 */
function GOSJLoad(json, readOnly) {
    if (!json) {
        json = {};
    }
    if (typeof json === "string") {
        json = JSON.parse(json);
    }
    GOJS.myDiagram.model = go.Model.fromJson(json);
    // GOJS.myDiagram.delayInitialization(function() {
    //   GOJS.myDiagram.requestUpdate();
    // });
    GOJS.setOpacity(!readOnly); // 默认为透明
    reData(true);
    GOJS.isReadOnly(readOnly); // 默认只读
    // GOJS.myDiagram.computebounds();
    // GOJS.myDiagram.delayinitialization();
}

/**
 * 节点双击事件/默认为空 后期与页面交互部分加载
 * @param e  事件对象
 * @param obj 选中的对象 节点/连线
 */
GOJS.mClick = function(e, obj) {
    const part = obj.part.data;
    // if (
    //     (part.category == "datatitle" && part.readWrite == "W") ||
    //     (part.category == "datatitle" && part.readWrite == "w")
    // )
    if (part.category == "datatitle") {
        // 下发
        vm.dialogFormVisible = true;
        vm.form.title = part.vname || part.nname;
        vm.form.id = part.id;

        if (part.enums && part.enums.length > 0) {
            vm.form.dataType = "list";
            const arr = part.enums.map((item) => {
                // number转化
                item.value = Number(item.value);
                return item;
            });
            vm.enumsOptions = arr;
        } else {
            vm.form.dataType = "text";
        }
        vm.form.value = part.value;
    }
    if (part.category == "Comment" && part.heatSourceId && part.pathId) {
        // 跳转功能
        vm.goBackPage(part);
    }
};

/**
 * 设置管路连接点的透明度
 * 编辑模式完全不透明 true
 * 展示模式完全透明   false
 * @param opacity
 */
GOJS.setOpacity = function(opacity) {
    GOJS.myDiagram.nodes.each(function(node) {
        var data = node.part.data;
        if (opacity) {
            data.opacity = 0.5;
        } else {
            data.opacity = 0;
        }

        GOJS.myDiagram.model.updateTargetBindings(data);
    });
};

// 设置只读属性
GOJS.isReadOnly = function(isReadOnly) {
    GOJS.myDiagram.isReadOnly = isReadOnly;
};

/**
 * 节点动画效果
 */
GOJS.loopNode = function() {
    GOJS.myDiagram.nodes.each(function(node) {
        var data = node.part.data;
        if (data.dyn && data.dyn > 0 && data.dy > 0) {
            if (data.yd == null || data.yd + 1 > data.dy) {
                data.yd = 1;
            } else {
                data.yd = data.yd + 1;
            }
            GOJS.myDiagram.model.updateTargetBindings(data);
        }
    });
    timer.at("gojs.loopNode", GOJS.loopNode, 500);
};

/**
 * 管道动态效果
 */
GOJS.opacity = 1; // 管道动态连线所需的透明度，默认不透明
GOJS.down = true; // 管道动态连线所需的公共变量
GOJS.loopLink = function() {
    var diagram = GOJS.myDiagram;
    var oldskips = diagram.skipsUndoManager;
    diagram.skipsUndoManager = true;
    diagram.links.each(function(link) {
        var d = link.part.data;
        if (d.dyn == 1) {
            var shape = link.findObject("PIPE");
            if (shape) {
                var off = shape.strokeDashOffset - 3;
                // animate (move) the stroke dash
                shape.strokeDashOffset = off <= 0 ? 60 : off;
                // animte (strobe) the opacity:
                if (GOJS.down) GOJS.opacity = GOJS.opacity - 0.02;
                else GOJS.opacity = GOJS.opacity + 0.006;
                if (GOJS.opacity <= 0) {
                    GOJS.down = !GOJS.down;
                    GOJS.opacity = 0;
                }
                if (GOJS.opacity > 1) {
                    GOJS.down = !GOJS.down;
                    GOJS.opacity = 1;
                }
                shape.opacity = GOJS.opacity;
            }
        }
    });
    diagram.skipsUndoManager = oldskips;
    timer.at("gojs.loopLink", GOJS.loopLink, 100);
};

/**
 * 图形加载后进行数据刷新
 */
function reData(cycle) {
    var model = GOJS.myDiagram.model;
    var node = model.nodeDataArray;
    var link = model.linkDataArray;

    if (node.length > 0 || link.length > 0) {
        var delList = "";
        // 循环所有组态图节点生成需要更新的数据点
        for (var k in node) {
            if (node[k]["devDetailed"]) {
                if (delList.length == 0) {
                    delList += node[k]["devDetailed"];
                } else {
                    delList = delList + "," + node[k]["devDetailed"];
                }
            }
        }
        for (var d in link) {
            if (link[d]["devDetailed"]) {
                if (delList.length == 0) {
                    delList += link[d]["devDetailed"];
                } else {
                    delList = delList + "," + link[d]["devDetailed"];
                }
            }
        }

        getRealDataAnds({ dataCode: delList }).then((res) => {
            const data = res.data.data;
            var datakey = {};
            for (var a in data) {
                datakey[data[a]["id"]] = data[a];
            }

            for (const k in node) {
                if (datakey[node[k]["devDetailed"]]) {
                    node[k]["id"] = datakey[node[k]["devDetailed"]]["id"];
                    node[k]["value"] = datakey[node[k]["devDetailed"]]["value"];

                    const date = datakey[node[k]["devDetailed"]]["date"];
                    node[k]["date"] = date ?
                        parseTime(date, "{y}-{m}-{d} {h}:{i}:{s}") :
                        "";
                    if (!node[k]["nname"] || node[k]["nname"] == node[k]["name"]) {
                        node[k]["vname"] = datakey[node[k]["devDetailed"]]["dataName"];
                    }
                    node[k]["onLine"] = datakey[node[k]["devDetailed"]]["stat"];
                    node[k]["warning"] = datakey[node[k]["devDetailed"]]["warning"];

                    if (datakey[node[k]["devDetailed"]]["value"] > 0) {
                        node[k]["dyn"] = 1;
                    } else {
                        node[k]["dyn"] = 0;
                    }

                    if (datakey[node[k]["devDetailed"]]["enume"]) {
                        if (datakey[node[k]["devDetailed"]]["enume"].length > 0) {
                            node[k]["enums"] = datakey[node[k]["devDetailed"]]["enume"];
                            node[k]["enums_list"] = node[k]["enums"].filter(
                                (item) => item.value == node[k]["value"]
                            )[0];
                            node[k]["enums_value"] = node[k]["enums_list"] ?
                                node[k]["enums_list"]["name"] :
                                node[k]["value"];
                        } else {
                            delete node[k]["enums"];
                            delete node[k]["enums_list"];
                            delete node[k]["enums_value"];
                        }
                    }
                    if (node[k].onLine === "在线" && node[k].warning === 0) {
                        node[k].stroke = vm.addForm.alarmColor;
                    } else if (node[k].onLine === "离线") {
                        node[k].stroke = vm.addForm.normalDataColor;
                    }

                    node[k]["heatSourceId"] =
                        datakey[node[k]["devDetailed"]]["heatSourceId"];
                    node[k]["heatStationId"] =
                        datakey[node[k]["devDetailed"]]["heatStationId"];
                    node[k]["heatSystemId"] =
                        datakey[node[k]["devDetailed"]]["heatSystemId"];

                    GOJS.myDiagram.model.updateTargetBindings(node[k]);
                }
            }

            for (var y in link) {
                if (
                    datakey[link[y]["devDetailed"]] &&
                    datakey[link[y]["devDetailed"]]["value"] > 0
                ) {
                    link[y]["dyn"] = 1;
                } else {
                    link[y]["dyn"] = 0;
                }
                GOJS.myDiagram.model.updateTargetBindings(link[k]);
            }

            if (cycle) {
                timer.at(
                    "reData",
                    function() {
                        reData(cycle);
                    },
                    10000
                );
            }
        });
    }
}

export default {
    setVm,
    GOJSInit,
    GOSJLoad,
};